# -*- coding: utf-8 -*-
import time
import requests
from PIL import Image
from io import BytesIO
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException, UnexpectedAlertPresentException
from taobao_check.tools import UserInfo, BaseSelenium, OCR, merge_image, print_log, get_browser


app_id = "24476366"
key = "TLWm2bkGv2C32uU7CbRDEeFI"
secret = "K41AGQgeT42erkWIQXGXBoAjoEDQPewA"


class MagicMirror(BaseSelenium):
    login_url = "http://139.159.141.200/app/superscanPH/loginPHValidate.jsp"
    check_url = "http://139.159.141.200/app/superscanPH/searchAliimPH.jsp"
    back_login_url = "http://49.234.132.215/app/superscanPH/loginPHValidate.jsp"
    base_check_url = "http://49.234.132.215/app/superscanPH/searchAliimPH.jsp"

    def __init__(self, username: str, password: str, print_log=print_log, debug=False, no_log=False):
        """
        照妖镜的初始化函数
        Args:
            username: 用户名，一般是手机号
            password: 密码
            print_log: 打印日志的函数，必须要接受一个debug参数，debug为True时不打印
            debug: 照妖镜的debug，为True时不显示浏览器界面
            no_log: 是否初始化的时候不打印日志
        """
        super().__init__()
        self.username = username
        self.password = password
        self.print_log = print_log
        self.debug = debug
        self.ocr = OCR                              # 用于OCR识别
        self.last_get_image = time.time()           # 由于照妖镜有反爬虫机制，如果请求太频繁就会被限制，
        self.interval = 2                           # 所以这两个参数就是用来控制请求的频率的
        self.error_time = 0
        self.init_env(no_log)

    def init_env(self, no_log=False) -> None:
        """
        初始化浏览器并登录照妖镜
        Args:
            no_log: 为True表示不打印日志
        Returns:
            None
        """
        self.env_ok = False
        self.print_log("开始登录照妖镜....", no_log)
        start = time.time()
        self.quit()
        if self.debug:
            self.browser = get_browser(headless=False, load_image=True)
        else:
            self.browser = get_browser(load_image=True)
        self.login()
        self.env_ok = True
        self.print_log(f"照妖镜登录成功!用时: {time.time() - start:.2f}s", no_log)

    def login(self) -> None:
        """
        登录照妖镜
        Returns:
            None
        """
        if self.browser.current_url != self.login_url:
            self.browser.get(self.login_url)

        self.enter_text((By.NAME, "username"), self.username)
        self.enter_text((By.NAME, "password"), self.password)
        self.click_button((By.CSS_SELECTOR, "a.regbtn"))

        while "loginPHValidate" not in self.browser.current_url:
            time.sleep(0.1)

    def search_user(self, username: str) -> [UserInfo, None]:
        """
        搜索一个用户
        Args:
            username: 用户名
        Returns:
            用户信息的类，如果遇到弹窗则返回None
        """
        # 每次刷新一下搜索界面防止登录过期
        self.browser.get(self.check_url)
        time.sleep(0.2)
        if "loginPHValidate" in self.browser.current_url:
            self.login()
        # 输入用户ID并搜索
        user_entry = self.enter_text((By.ID, "aliim"), username)
        user_entry.send_keys(Keys.ENTER)

        try:
            wait = self.wait_search_result()
            if not wait:
                raise TimeoutException
            return self.parse_result(username)
        except UnexpectedAlertPresentException as e:
            # 这个是捕获Alert弹窗的，目前已知的弹窗有：1.用户不存在，2.用户名长度非法, 3.查验限额
            return None

    def wait_search_result(self):
        """
        按下搜索按钮后，需要等待搜索结果加载
        Returns:
            如果成功加载就返回True，超时还未加载出来就返回False
        """
        check_button = WebDriverWait(self.browser, self.timeout). \
            until(EC.presence_of_element_located((By.CSS_SELECTOR, "div.hidebox")))

        start_time = time.time()
        while check_button.get_attribute('style') is None:
            time.sleep(0.1)
            if time.time() - start_time > self.timeout:
                return False

        return True

    def get_image(self, selector: tuple) -> Image:
        """
        获得页面上的图像
        Args:
            selector: 选择器，用于定位图像的位置
        Returns:
            如果下载成功则返回图像的PIL.Image对象，否则返回None
        """
        if time.time() - self.last_get_image < self.interval:
            time.sleep(self.interval - time.time() + self.last_get_image + 0.2)
        self.last_get_image = time.time()
        element = self.find_element(selector)
        imgurl = element.get_attribute('src')

        headers = {
            "User-Agent":
                "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36"
        }
        s = requests.session()
        s.headers.update(headers)

        for cookie in self.browser.get_cookies():
            c = {cookie['name']: cookie['value']}
            s.cookies.update(c)

        r = s.get(imgurl, allow_redirects=True)

        if r.status_code == 200:
            return Image.open(BytesIO(r.content))
        else:
            self.print_log(f"照妖镜下载图片失败, url: {imgurl}", debug=True)
            self.login()
            return None

    def parse_result_by_html(self, username: str):
        """解析查询页面中的数据，应保证调用这个函数时的页面是成功查询的结果"""
        down = self.browser.find_element_by_id("downNum")
        start_time = time.time()
        while down.get_attribute('textContent') == "":
            time.sleep(0.1)
            if time.time() - start_time > self.timeout:
                return None

        user = UserInfo(username, mirror=True)
        # 买家信誉
        credit = self.browser.find_element_by_id("buyerCre").text
        if len(credit) > 1:
            user.credit_type = credit[1:]
            user.credit_level = int(credit[0])
        # 周平均
        week_avg = self.browser.find_element_by_id("buyerAvg").text
        try:
            if len(week_avg) > 0:
                if week_avg[0] == "约":
                    user.week_avg = float(week_avg[1:])
                else:
                    user.week_avg = float(week_avg)
        except:
            pass
        # 各种狐狸行为
        acticon_list = ["tz", "mg", "hl", "ey", "yg", "ls"]
        for acticon in acticon_list:
            user.fox += int(self.browser.find_element_by_id(acticon).get_attribute('textContent'))
        # 降权
        user.downright = int(self.browser.find_element_by_id("downNum").get_attribute('textContent'))
        # 近一周查询人数
        user.near_week_check = int(self.browser.find_element_by_id("nearWeekShop").text)
        # # 上一周查询人数
        user.last_week_check = int(self.browser.find_element_by_id("lastWeekShop").get_attribute('textContent'))

        return user

    def parse_result_by_image(self, username: str):
        user = UserInfo(username, mirror=True)
        try:
            buyer = self.get_image((By.CSS_SELECTOR, "div.wwdata>img"))
            mark = self.get_image((By.CSS_SELECTOR, "div.down>img"))
        except Exception as e:
            self.print_log("照妖镜无法使用，默认通过。")
            self.error_time += 1
            return None
        buyer = merge_image(buyer, mark)
        if not buyer:
            return None

        result = self.ocr.ocr(buyer)
        self.print_log(f"OCR识别结果: {result}", debug=True)

        for idx, word in enumerate(result):
            try:
                if "买家总周平均:" in word:
                    user.week_avg = float(word.replace("买家总周平均:", "").replace("约", "").strip())
                elif "本周查过商家:" in word and "上周查过商家:" in word:
                    s = [i.split("上周查过商家:") for i in word.split("本周查过商家:") if i]
                    if len(s) < 1:
                        continue
                    s = s[0]
                    if len(s) > 0:
                        user.near_week_check = int(s[0].strip())
                    if len(s) > 1:
                        user.last_week_check = int(s[1].strip())
                elif "本周查过商家:" in word:
                    user.near_week_check = int(word.replace("本周查过商家:", "").strip())
                elif "上周查过商家:" in word:
                    user.last_week_check = int(word.replace("上周查过商家:", "").strip())
                elif "好评:" in word:
                    user.downright = int(result[idx-1])
            except Exception as e:
                self.print_log(f"解析OCR识别结果出错: {e}", debug=True)

        self.error_time = 0
        return user

    def parse_result(self, username: str):
        """
        解析查询页面中的数据，应保证调用这个函数时的页面是成功查询的结果
        Args:
            username: 要查询的用户名
        Returns:
            用户信息类，可能有部分信息没有解析到
        """
        if self.error_time > 3 and self.error_time % 10 != 0:
            self.print_log("照妖镜无法使用，默认通过。")
            return None

        try:
            return self.parse_result_by_html(username)
        except Exception as e:
            return self.parse_result_by_image(username)

    @staticmethod
    def check(user: UserInfo) -> bool:
        """
        查验一个用户是否符合要求
        Args:
            user: UserInfo对象
        Returns:
            查验结果
        """
        if user is None:
            return True
        if user.downright > 0:
            return False
        if user.near_week_check > 7:
            return False
        if user.last_week_check > 7:
            return False
        if user.week_avg >= 1.8:
            return False

        return True

    def quit(self):
        try:
            self.browser.quit()
        except:
            pass


if __name__ == "__main__":
    from random import choice
    mm = MagicMirror('15305952007', 'ancheng123', debug=True)
    print("搜索")
    names = ['tb291924592', 'qwert墨颜墨颜', 'qw4u7ac094', 'tb139619860', '幻莲晓', '如今购买力', '心缘坊服饰8', '王硕明222', '打败小s', '黄启芽','13473127800song', 'tb36471219', '不爱我717', 'tb339763558', '黄金万两1014', 'fabrecaca', 'tb028540227', '阶蒙不才子', '你好先生好你', 'alicefushiwood', 'cbu-qhjy988', 'kvxtny38713', 't_1486254809199_012', 'tb8176611_2011', '南宇汽车装饰店', '扈心75202', '陶德723', 'tb035204148', 'liruijia775', '胡滔专属', 'lm30920', 'tb870052376', '金城电动', '我是怡君唷', 'jim1242012', '2020岁岁常相见', 'mlq1021750506', 'bjai21', 'songxh8898', 'caozhenghui2013', '越努力越幸福z', 'nununa2009', 'longfei714abc', '一心一意8057', '浮生v妄言', '洪罩瞧', 'd997093730', '岁月不等人629', '王光军9032', 'aa337244017', '新城蓝色妖姬', '依储晓沁cand', 'tb089741878', 'yujiang110', 'tb367292645', 'tb_8896893', 'tb367604123', 'ljmxrx', 'ossianhowley', '亲亲宝贝吧588', 'jay8819129', '我的心都碎了74', '没齿难忘142', 'cbu-jedsir', '徐y悦qh', '史美芳881121', 'jasfish37', '低调de繁华0', '飞来的橘', 'a8x8gy9t18u6', 'wengsh666', 'cbu-xiongjie0103', '大洋冰鸽233', 'feimengcat', 'joanwang_5', '邓显这140390', 'rizdavid', '快乐兰瑟', 'tb434332593', '颖关友102929', '爱你菲宝哟', '幸福味道1213', 'tb424975077', '郑双定', 'aoxinghuojia', '子轩奕涵', '陌上人如玉841110', '哭泣的秋天', 'tb616420273', '生活继续中任悦', '饶江河', '小可爱曼祎', '柠凉初夏', 'yang750415', '年少怎么能不猖狂', 'cm54321_2009', '小林林1990318', 'jindai', 'yoyo125811', '阿珏少爷', 'tb0219175025', 'vc海贼王', 'tb612250484', 'hpqingfeng2009', '排圩6队', 'cbu-zhaohuixinyuan', 'mp249553', '黑色嗨客', 'yanbolu1996', 'tb342739016', 'tb2565725863', '云上の天空', '江国春88', '叮叮咚19903', 'tb128248233', '茵茵春天', '花开花谢8494', 'tb3684074767', 'koala2230', '紫凝2335', '兰宝贝2008', '爱莫霖琳', '香香榴莲1985', '肌拇本闭', '冰凌花63682', '啊707547006', '晁梵紫菀苏', '我行我素1296', 'xiajiani', '小石520475', 'tmd303', '万事xc如意', '一根天使的羽毛糖', '冰是睡着的水18769371', 'bsing007', 'tb453703445', '神界仙灵', 'chenqindian', 't_1513508324099_0734', '早早交货了', 't_1488724323167_0901', '靖宝爱你1988', '平平安安0409', '回忆里模糊的样子', 'basaby', 'lioiioil', 'maxiaoting2010', 'us敏林308', '我只会黄哈哈', 'qq710983318', 'tb35957209', 'tb86733101', '有扇子', '倾城倾城99', 'muziyuepengpeng', 'tb67050375', '费飞飞520', 'tb4891125391', 'kxdd99', '兜兜里面有糖丶', '香巷子宽', 'qinqingdenglu9', '吴晓华1314520', '度果到一边', '1218丹', 'tb77032913', 'tb437455754', '陈姗云', '残梦照祠堂', 'lgx10001388', 'luolijun13878367735', '柠檬脾气83204513', '奥黛丽赫本zara', '芹菜萝卜我都爱', 'yujuang回忆童年', '564841200qqcom', 'dodolook27', 'j4564466', 't_1491813559180_015', '痪庇汕', 'tb04650736', '亦凝桃', '管扯佑仍释', 'a79719972', '凄美的暧昧', 'gourry3661', 'liyonglin88', 'boey_777', '阿巴阿巴咔咔', 't_1511101867437_0928', '雨点的故事88', 'tb7308246561', '二丫994', '季佳婕', 'tb4483457123', 'madqxf76', 'aiyanlove1314', 'tb53207802', '飞花飞叶88', 'tongrachel']
    result = mm.search_user(choice(names))
    print(result)
    mm.quit()

